"use strict";

const semver = require("semver");
const colors = require("colors/safe");
const log = require("@liusion-cli-dev/log");
const init = require("@liusion-cli-dev/init");
const exec = require("@liusion-cli-dev/exec");
const rootCheck = require("root-check");
const userHome = require("user-home");
const pathExists = require("path-exists").sync;
const path = require("path");
const commander = require("commander");
const program = new commander.Command();

const pkg = require("../package.json");
const constant = require("./const");

function checkRoot() {
  rootCheck();
}

function checkNodeVersion() {
  const currentVersion = process.version;
  const lowestVersion = constant.LOWEST_NODE_VERSION;
  if (!semver.gte(currentVersion, lowestVersion)) {
    throw new Error(
      colors.red(`liusion-cli需要安装 v${lowestVersion} 以上版本的Node.js`)
    );
  }
}

function checkPackageVersion() {
  log.notice("cli", pkg.version);
}

function checkUserHome() {
  if (!userHome || !pathExists(userHome)) {
    throw new Error(colors.red("当前用户登录用户主目录不存在！"));
  }
  console.log(userHome);
}

function checkInputArgs() {
  const minimist = require("minimist");
  const args = minimist(process.argv.slice(2));
  checkArgs(args);
}

function checkArgs(args) {
  process.env.LOG_LEVEL = args.debug ? "verbose" : "info";
  log.level = process.env.LOG_LEVEL;
}

function checkEnv() {
  const dotenv = require("dotenv");
  const dotEnvPath = path.resolve(userHome, ".env");
  console.log("dotEnvPath", dotEnvPath);
  if (pathExists(dotEnvPath)) {
    dotenv.config({
      path: dotEnvPath,
    });
  }
  createDefaultConfig();
  log.verbose("环境变量", process.env.CLI_HOME_PATH);
}

function createDefaultConfig() {
  const cliConfig = {
    home: userHome,
  };
  if (process.env.CLI_HOME) {
    cliConfig["cliHome"] = path.join(userHome, process.env.CLI_HOME);
  } else {
    cliConfig["cliHome"] = path.join(userHome, constant.DEFAULT_CLI_HOME);
  }
  process.env.CLI_HOME_PATH = cliConfig.cliHome;
  return cliConfig;
}

async function checkGlobalUpdate() {
  const currentVersion = pkg.version;
  const npmName = pkg.name;
  const { getNpmSemverVersion } = require("@liusion-cli-dev/get-npm-info");
  const lastVersion = await getNpmSemverVersion(currentVersion, npmName);
  if (lastVersion && semver.gt(lastVersion, currentVersion)) {
    log.warn(
      colors.yellow(
        `请手动更新${npmName}，当前版本${currentVersion}，最新版本${lastVersion}`
      )
    );
  }
}

function registerCommand() {
  console.log("process.argv", process.argv);
  program
    .name(Object.keys(pkg.bin)[0])
    .usage("<command> [options]")
    .version(pkg.version)
    .option("-d, --debug", "是否开启调试模式", false)
    .option("-tp, --targetPath <targetPath>", "是否指定本地调试文件路径", "");

  program
    .command("init [projectName]")
    .option("-f, --force", "是否强制初始化项目")
    .action(exec);

  program.on("option:debug", function () {
    console.log("on option:debug");
    process.env.LOG_LEVEL = this.opts().debug ? "verbose" : "info";
    log.level = process.env.LOG_LEVEL;
    log.verbose("test", "test debug log");
  });

  program.on("option:targetPath", function () {
    console.log("program targetPath", program._optionValues.targetPath);
    process.env.CLI_TARGET_PATH = program._optionValues.targetPath;
  });
  program.on("command:*", function (obj) {
    const availableCommands = program.commands.map((cmd) => cmd.name());
    console.log("program.commands", program.commands);
    console.log(colors.red("未知命令：" + obj[0]));
    if (availableCommands.length > 0) {
      console.log(colors.red("可用命令" + availableCommands.join(",")));
    }
  });

  program.parse(process.argv);
  // process.argv.length < 3
  // if (program.args && program.args.length < 1) {
  //   program.outputHelp();
  // }
}

async function prepare() {
  checkNodeVersion();
  checkPackageVersion();
  checkRoot();
  checkUserHome();
  // checkInputArgs();
  checkEnv();
  await checkGlobalUpdate();
}

async function core() {
  try {
    await prepare();
    registerCommand();
  } catch (e) {
    log.error(e.message);
  }
}

module.exports = core;
